var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "path", "../../../ext/turf", "axios", "../../../com/configTool", "../Util/readFromDB", "../Util/readFromNet", "../Util/saveToDB", "../Util/saveToFile", "../Util/initDB", "../../../lib/awaitWrap", "../../../lib/TileTool/TileUtil4326", "../../TileTool/TileSet", "../Util/readFromDisk"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    const path_1 = __importDefault(require("path"));
    const turf_1 = __importDefault(require("../../../ext/turf"));
    const axios_1 = __importDefault(require("axios"));
    const configTool_1 = __importDefault(require("../../../com/configTool"));
    const readFromDB_1 = __importDefault(require("../Util/readFromDB"));
    const readFromNet_1 = __importDefault(require("../Util/readFromNet"));
    const saveToDB_1 = __importDefault(require("../Util/saveToDB"));
    const saveToFile_1 = __importDefault(require("../Util/saveToFile"));
    const initDB_1 = __importDefault(require("../Util/initDB"));
    const awaitWrap_1 = __importDefault(require("../../../lib/awaitWrap"));
    const TileUtil4326_1 = __importDefault(require("../../../lib/TileTool/TileUtil4326"));
    const TileSet_1 = __importDefault(require("../../TileTool/TileSet"));
    const readFromDisk_1 = __importDefault(require("../Util/readFromDisk"));
    const World = require('./World.json');
    let loading = false;
    const DBName = 'CesiumWorldTerrain';
    const baseUrl = 'https://assets.ion.cesium.com/asset_depot/1/CesiumWorldTerrain/v1.2/';
    const ext = '?extensions=octvertexnormals-watermask-metadata&v=1.2.0';
    const Cesium = require('Cesium/Build/Cesium/index.cjs');
    let Authorization = '';
    const defaultAccessToken = Cesium.Ion.defaultAccessToken;
    let CesiumTerrain = {
        async init() {
            await configTool_1.default.init();
            configTool_1.default.preservableONDB() && await (0, initDB_1.default)(DBName);
        },
        async ionAuthority() {
            if (loading) {
                await new Promise((resolve) => {
                    let timer = setInterval(() => {
                        if (!loading) {
                            clearInterval(timer);
                            resolve(null);
                        }
                    }, 100);
                });
            }
            if (!Authorization) {
                loading = true;
                let [err, data] = await (0, awaitWrap_1.default)(axios_1.default.get('https://api.cesium.com/v1/assets/1/endpoint?access_token=' + defaultAccessToken));
                loading = false;
                if (data) {
                    data = data.data;
                    Authorization = 'Bearer ' + data.accessToken;
                    console.log('获取令牌成功', data.accessToken);
                }
                else {
                    console.log(Cesium.Ion.defaultAccessToken);
                    console.log('获取令牌失败');
                }
            }
        },
        async getFileBuffer(url) {
            await this.init();
            let err, buffer, dataSource;
            let headers = { 'Authorization': Authorization };
            let relativePath = '\\1\\' + url;
            let fileSavePath = path_1.default.join(configTool_1.default.appBasePath, `temp/fileOut/assets.cesium.com`, relativePath);
            [err, buffer, dataSource] = await (0, readFromDisk_1.default)({ fileSavePath, err, buffer, dataSource });
            [err, buffer, dataSource] = await (0, readFromDB_1.default)({ DBName, relativePath, err, buffer, dataSource });
            if (!buffer) {
                await this.ionAuthority();
                [err, buffer, dataSource] = await (0, readFromNet_1.default)({ url: baseUrl + url + ext, headers, err, buffer, dataSource });
            }
            if (err?.state === 404) {
            }
            else if (err?.state === 503) {
                console.log('请求过于频繁，服务器拒绝响应');
            }
            else if (err?.state === 401) {
                console.log(err);
                console.log('重置 Cesium 地形资源的 令牌');
                Authorization = '';
            }
            buffer && dataSource !== 'DB' && configTool_1.default.preservableONDB() && (0, saveToDB_1.default)({ DBName, relativePath, buffer }, true).then();
            buffer && dataSource === 'Net' && configTool_1.default.preservableONFile() && (0, saveToFile_1.default)(fileSavePath, buffer).then();
            return [err, buffer];
        },
        async getTileListByGeoJson(zoom, geoJson, layerJson) {
            await this.init();
            const tileUtil4326 = new TileUtil4326_1.default();
            geoJson = geoJson || World;
            if (!layerJson) {
                const [err, buffer] = await CesiumTerrain.getFileBuffer('layer.json');
                layerJson = buffer ? JSON.parse(buffer.toString()) : null;
                if (err || layerJson === null) {
                    return { tileList: [], boxList: [] };
                }
            }
            const dataRanges = layerJson.available;
            const tileSet = new TileSet_1.default();
            const boxList = [];
            const areaRangeList = dataRanges[zoom];
            const effectiveAreaRangeList = [];
            for (let i = 0; i < areaRangeList?.length; i++) {
                const rowAreaRange = areaRangeList[i];
                const rowMinTile = tileUtil4326.tileXYZToRectanglePolygon(rowAreaRange.startX, rowAreaRange.startY, zoom);
                const rowMaxTile = tileUtil4326.tileXYZToRectanglePolygon(rowAreaRange.endX, rowAreaRange.endY, zoom);
                const rowAreaBbox = turf_1.default.bbox(turf_1.default.featureCollection([rowMinTile, rowMaxTile]));
                const rowAreaBoxPolygon = turf_1.default.bboxPolygon(rowAreaBbox);
                if (turf_1.default.booleanDisjoint(geoJson, rowAreaBoxPolygon)) {
                    continue;
                }
                const polygons = [];
                turf_1.default.featureEach(geoJson, function (currentFeature) {
                    if (currentFeature.geometry.type === 'Polygon') {
                        polygons.push(currentFeature.geometry.coordinates);
                    }
                });
                const multiPoly = turf_1.default.multiPolygon(polygons);
                const clipGeoJson = turf_1.default.bboxClip(multiPoly, rowAreaBbox);
                const clipBbox = turf_1.default.bbox(clipGeoJson);
                const trimMinTile = tileUtil4326.getTileXYZ(clipBbox[0], clipBbox[1], zoom);
                const trimMaxTile = tileUtil4326.getTileXYZ(clipBbox[2], clipBbox[3], zoom);
                const trimRowAreaRange = {
                    endX: Math.min(trimMaxTile.x, rowAreaRange.endX),
                    endY: Math.min(trimMaxTile.y, rowAreaRange.endY),
                    startX: Math.max(trimMinTile.x, rowAreaRange.startX),
                    startY: Math.max(trimMinTile.y, rowAreaRange.startY)
                };
                const middle_1_3_X = trimRowAreaRange.startX + Math.floor((trimRowAreaRange.endX - trimRowAreaRange.startX) / 3) - 1;
                const middle_2_3_X = trimRowAreaRange.startX + Math.floor((trimRowAreaRange.endX - trimRowAreaRange.startX) / 3) * 2 - 1;
                const middle_1_3_Y = trimRowAreaRange.startY + Math.floor((trimRowAreaRange.endY - trimRowAreaRange.startY) / 3) - 1;
                const middle_2_3_Y = trimRowAreaRange.startY + Math.floor((trimRowAreaRange.endY - trimRowAreaRange.startY) / 3) * 2 - 1;
                const leafOne = { startX: trimRowAreaRange.startX, startY: trimRowAreaRange.startY, endX: middle_1_3_X, endY: middle_1_3_Y };
                const leafTwo = { startX: middle_1_3_X + 1, startY: trimRowAreaRange.startY, endX: middle_2_3_X, endY: middle_1_3_Y };
                const leafThree = { startX: trimRowAreaRange.startX, startY: middle_1_3_Y + 1, endX: middle_1_3_X, endY: middle_2_3_Y };
                const leafFour = { startX: middle_1_3_X + 1, startY: middle_1_3_Y + 1, endX: middle_2_3_X, endY: middle_2_3_Y };
                const leafFive = { startX: middle_2_3_X + 1, startY: trimRowAreaRange.startY, endX: trimRowAreaRange.endX, endY: middle_1_3_Y };
                const leafSix = { startX: middle_2_3_X + 1, startY: middle_1_3_Y + 1, endX: trimRowAreaRange.endX, endY: middle_2_3_Y };
                const leafSeven = { startX: trimRowAreaRange.startX, startY: middle_2_3_Y + 1, endX: middle_1_3_X, endY: trimRowAreaRange.endY };
                const leafEight = { startX: middle_2_3_X + 1, startY: middle_2_3_Y + 1, endX: trimRowAreaRange.endX, endY: trimRowAreaRange.endY };
                const leafNine = { startX: middle_1_3_X + 1, startY: middle_2_3_Y + 1, endX: middle_2_3_X, endY: trimRowAreaRange.endY };
                const leafList = [leafOne, leafTwo, leafThree, leafFour, leafFive, leafSix, leafSeven, leafEight, leafNine];
                for (let j = 0; j < leafList.length; j++) {
                    const leafAreaRange = leafList[j];
                    const minTile = tileUtil4326.tileXYZToRectanglePolygon(leafAreaRange.startX, leafAreaRange.startY, zoom);
                    const maxTile = tileUtil4326.tileXYZToRectanglePolygon(leafAreaRange.endX, leafAreaRange.endY, zoom);
                    const areaBbox = turf_1.default.bbox(turf_1.default.featureCollection([minTile, maxTile]));
                    const areaBoxPolygon = turf_1.default.bboxPolygon(areaBbox);
                    if (!turf_1.default.booleanDisjoint(geoJson, areaBoxPolygon)) {
                        const polygons = [];
                        turf_1.default.featureEach(geoJson, function (currentFeature) {
                            if (currentFeature.geometry.type === 'Polygon') {
                                polygons.push(currentFeature.geometry.coordinates);
                            }
                        });
                        const multiPoly = turf_1.default.multiPolygon(polygons);
                        const clipGeoJson = turf_1.default.bboxClip(multiPoly, areaBbox);
                        const clipBbox = turf_1.default.bbox(clipGeoJson);
                        const trimMinTile = tileUtil4326.getTileXYZ(clipBbox[0], clipBbox[1], zoom);
                        const trimMaxTile = tileUtil4326.getTileXYZ(clipBbox[2], clipBbox[3], zoom);
                        const areaRange = {
                            endX: Math.min(trimMaxTile.x, leafAreaRange.endX),
                            endY: Math.min(trimMaxTile.y, leafAreaRange.endY),
                            startX: Math.max(trimMinTile.x, leafAreaRange.startX),
                            startY: Math.max(trimMinTile.y, leafAreaRange.startY)
                        };
                        const areaRangeBox = turf_1.default.bboxPolygon(turf_1.default.bbox(turf_1.default.featureCollection([
                            tileUtil4326.tileXYZToRectanglePolygon(areaRange.startX, areaRange.startY, zoom),
                            tileUtil4326.tileXYZToRectanglePolygon(areaRange.endX, areaRange.endY, zoom)
                        ])));
                        boxList.push(areaRangeBox);
                        effectiveAreaRangeList.push(areaRange);
                        for (let x = areaRange.startX; x <= areaRange.endX; x++) {
                            for (let y = areaRange.startY; y <= areaRange.endY; y++) {
                                tileSet.add(x, y, zoom);
                            }
                        }
                    }
                }
            }
            return { tileList: tileSet.getAll(), boxList, effectiveAreaRangeList };
        }
    };
    exports.default = CesiumTerrain;
});
